package com.hiof.connection.observers;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import com.android.future.usb.UsbAccessory;
import com.android.future.usb.UsbManager;
import com.hiof.Configuration;
import com.hiof.connection.ConnectionManager;
import com.hiof.connection.DataReceiveHandler;
import com.hiof.utility.Utility;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

/**
 * Created by IntelliJ IDEA.
 * User: manish
 * Date: 4/9/12
 * Time: 9:11 PM
 * To change this template use File | Settings | File Templates.
 */
public class USBConnectionManager implements Runnable, ConnectionManager {
        private static final String TAG = "USB connection";
        ArrayList<ConnectionObserver> observers;
        private static USBConnectionManager instance;


    private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION";

    private UsbManager mUsbManager;
    private PendingIntent mPermissionIntent;
    private boolean mPermissionRequestPending;

    UsbAccessory mAccessory;
    ParcelFileDescriptor mFileDescriptor;
    FileInputStream mInputStream;
    FileOutputStream mOutputStream;
    DataReceiveHandler dataReceiveHandler;

    private USBConnectionManager() {
        observers = new ArrayList<ConnectionObserver>();
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
        dataReceiveHandler = new DataReceiveHandler();
        Configuration.getInstance().getCurrentContext().registerReceiver(mUsbReceiver, filter);
    }

    public static USBConnectionManager getInstance() {
        if (instance == null) {
            instance = new USBConnectionManager();
        }
        return instance;
    }

    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbAccessory accessory = UsbManager.getAccessory(intent);
                    if (intent.getBooleanExtra(
                            UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        openAccessory(accessory);
                    } else {
                        Utility.debug(this.getClass().toString(), "permission denied for accessory "
                                + accessory);
                    }
                    mPermissionRequestPending = false;
                }
            } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
                UsbAccessory accessory = UsbManager.getAccessory(intent);
                if (accessory != null && accessory.equals(mAccessory)) {
                    close();
                }
            }
        }
    };

    private void openAccessory(UsbAccessory accessory) {
        mFileDescriptor = mUsbManager.openAccessory(accessory);
        if (mFileDescriptor != null) {
            mAccessory = accessory;
            FileDescriptor fd = mFileDescriptor.getFileDescriptor();
            mInputStream = new FileInputStream(fd);
            mOutputStream = new FileOutputStream(fd);
            Thread t = new Thread(this);
            t.start();
            Utility.debug(this.getClass().toString(), "accessory opened");
        } else {
            Utility.debug(this.getClass().toString(), "accessory open failed");
        }
    }

    @Override
    public void open() {
        UsbAccessory accessory = (UsbAccessory) ((Activity)Configuration.getInstance().getCurrentContext()).getLastNonConfigurationInstance();
        openAccessory(accessory);
    }

    @Override
    public void close() {
        try {
            if (mFileDescriptor != null) {
                mFileDescriptor.close();
                
            } if(null != mUsbReceiver){
                Configuration.getInstance().getCurrentContext().unregisterReceiver(mUsbReceiver);
            }
        } catch (IOException e) {
        } finally {
            mFileDescriptor = null;
            mAccessory = null;
        }
    }

    @Override
    public void restart() {
        if (mInputStream != null && mOutputStream != null) {
            return;
        }

        UsbAccessory[] accessories = mUsbManager.getAccessoryList();
        UsbAccessory accessory = (accessories == null ? null : accessories[0]);
        if (accessory != null) {
            if (mUsbManager.hasPermission(accessory)) {
                openAccessory(accessory);
            } else {
                synchronized (mUsbReceiver) {
                    if (!mPermissionRequestPending) {
                        mUsbManager.requestPermission(accessory,
                                mPermissionIntent);
                        mPermissionRequestPending = true;
                    }
                }
            }
        } else {
            Utility.debug(this.getClass().toString(),"mAccessory is null");
        }
    }

    @Override
    public void registerObserver(ConnectionObserver observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(ConnectionObserver observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void run() {
        int ret = 0;
        byte[] buffer = new byte[16384];
        int i;
        while (ret >= 0) {
            try {
                ret = mInputStream.read(buffer);
            } catch (IOException e) {
                break;
            }

            i = 0;
            while (i < ret) {
                int len = ret - i;
                switch (buffer[i]) {
                    case 0x1:
                        if (len >= 2) {
                            if (buffer[i + 1] == 1) {
                                Message m = new Message();
                                Bundle b = new Bundle();
                                b.putString("message", "next");
                                m.setData(b);
                                dataReceiveHandler.sendMessage(m);
                            } else if (buffer[i + 1] == 2) {
                                Message m = new Message();
                                Bundle b = new Bundle();
                                b.putString("message", "previous");
                                m.setData(b);
                                dataReceiveHandler.sendMessage(m);
                            } else if (buffer[i + 1] == 3) {
                                Message m = new Message();
                                Bundle b = new Bundle();
                                b.putString("message", "cancel");
                                m.setData(b);
                                dataReceiveHandler.sendMessage(m);
                            } else if (buffer[i + 1] == 4) {
                                Message m = new Message();
                                Bundle b = new Bundle();
                                b.putString("message", "select");
                                m.setData(b);
                                dataReceiveHandler.sendMessage(m);
                            }
                        }
                        i += 2;
                        break;
                    default:
                        Utility.debug(this.getClass().toString(),"unknown msg: " + buffer[i]);
                        i = len;
                        Message m = new Message();
                        Bundle b = new Bundle();
                        b.putString("message", "errorr" +
                                "" +
                                "");
                        m.setData(b);
                        dataReceiveHandler.sendMessage(m);
                        break;
                }
            }
        }
    }

    /*Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if(msg.getData()!=null && !String.valueOf(msg.getData().get("message")).equals("null")){
                Toast.makeText(Configuration.getInstance().getCurrentContext(), msg.getData().get("message").toString(), Toast.LENGTH_LONG);
                if(msg.getData().get("message").equals("next")){
                    NavigationMenu.getInstance().next();
                }else if(msg.getData().get("message").equals("previous")){
                    NavigationMenu.getInstance().previous();
                }
                if(msg.getData().get("message").equals("select")){
                    NavigationMenu.getInstance().select();
                }
                if(msg.getData().get("message").equals("cancel")){
                    NavigationMenu.getInstance().cancel();
                }
            }else{
              Toast.makeText(Configuration.getInstance().getCurrentContext(), "Error:",Toast.LENGTH_SHORT).show();
            }
        }
    };*/
}

